from typing import Generator, Optional

from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from jose import jwt
from pydantic import ValidationError
from sqlalchemy.orm import Session

from app import crud, models, schemas
from app.core import security
from app.core.config import settings
from app.db.base import get_db

# OAuth2密码流认证方案，指定令牌URL
oauth2_scheme = OAuth2PasswordBearer(tokenUrl=f"{settings.API_V1_STR}/users/login")

def get_current_user(db: Session = Depends(get_db), token: str = Depends(oauth2_scheme)) -> models.User:
    """验证当前用户
    
    从请求中获取JWT令牌，验证其有效性并返回对应的用户对象
    
    Args:
        db: 数据库会话，通过依赖注入获取
        token: JWT令牌，通过OAuth2PasswordBearer依赖获取
        
    Returns:
        models.User: 当前用户对象
        
    Raises:
        HTTPException: 当令牌无效或用户不存在时抛出
    """
    try:
        payload = jwt.decode(
            token, settings.SECRET_KEY, algorithms=[security.ALGORITHM]
        )
        token_data = schemas.TokenPayload(**payload)
    except (jwt.JWTError, ValidationError):
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="无法验证凭据",
        )
    user = crud.user.get(db, id=token_data.sub)
    if not user:
        raise HTTPException(status_code=404, detail="用户不存在")
    return user

def get_current_active_user(current_user: models.User = Depends(get_current_user)) -> models.User:
    """验证当前用户是否激活
    
    检查用户的激活状态，确保只有激活的用户可以访问API
    
    Args:
        current_user: 当前用户对象，通过get_current_user依赖获取
        
    Returns:
        models.User: 当前激活的用户对象
        
    Raises:
        HTTPException: 当用户未激活时抛出
    """
    if not crud.user.is_active(current_user):
        raise HTTPException(status_code=400, detail="用户未激活")
    return current_user

def get_current_superuser(current_user: models.User = Depends(get_current_user)) -> models.User:
    """验证当前用户是否为超级管理员
    
    检查用户的超级管理员权限，确保只有超级管理员可以访问特定API
    
    Args:
        current_user: 当前用户对象，通过get_current_user依赖获取
        
    Returns:
        models.User: 当前超级管理员用户对象
        
    Raises:
        HTTPException: 当用户不是超级管理员时抛出
    """
    if not crud.user.is_superuser(current_user):
        raise HTTPException(
            status_code=400, detail="用户权限不足"
        )
    return current_user